package OOP;

import java.util.Arrays;
/**
 * 面向对象核心概念演示
 * 包含：继承、重载、重写、多态、转型等特性
 */
public class CoreOopDemo {


    // ==================== 继承示例 ====================
    static class InheritanceDemo extends Object{
        // 任何类，除了Object，都会继承自某个类
        // Java只允许一个class继承自一个类，因此，一个类有且仅有一个父类。只有Object特殊，它没有父类
        abstract static class Animal {
            protected int height; // 使用protected允许子类访问

            public Animal(int height) {
                this.height = height;
            }

            public void eat() {
                System.out.println("The animal is eating.");
            }

            // 抽象方法强制子类实现
            public abstract void move();
        }

        static class Dog extends Animal {   // 只需要编写额外的功能，不再需要重复代码
            private final String breed;

            public Dog(int height, String breed) {
                // 在Java中，任何class的构造方法，第一行语句必须是调用父类的构造方法
                super(height); // 调用父类构造方法
                this.breed = breed;
            }

            @Override
            public void eat() {
                System.out.println("Dog is eating from bowl.");
                super.eat(); // 调用父类方法
            }

            public void bark() {
                System.out.println("Woof! Woof!");
            }

            @Override
            public void move() {
                System.out.println("Running on four legs");
            }
        }

        public static void main(String[] args) {
            Dog goldenRetriever = new Dog(60, "Golden Retriever");
            System.out.println("多态——Java的方法调用总是作用于运行期对象的实际类型");
            goldenRetriever.eat();  // 输出两行信息
            goldenRetriever.bark();
            System.out.println("Dog height: " + goldenRetriever.height + "cm");
        }
    }


    // ==================== 方法重载示例 ====================
    static class OverloadDemo {
        static class Greeter {
            public void greet() {
                System.out.println("Hello, world!");
            }

            public void greet(String name) {
                System.out.printf("Hello, %s!%n", name);
            }

            public void greet(String name, int times) {
                String greeting = "Hi " + name +"加班" + times + "次";
                System.out.println(greeting);
            }
        }

        public static void main(String[] args) {
            System.out.println("方法名相同，但各自的参数不同，称为方法重载（Overload）,返回值类型通常都是相同的");
            Greeter greeter = new Greeter();
            greeter.greet();
            greeter.greet("Alice");
            greeter.greet("Bob", 3);
        }
    }



    // ==================== 方法重写示例 ====================
    static class OverrideDemo {
        static class Person {
            private final String name;

            public Person(String name) {
                this.name = name;
            }

            public void introduce() {
                System.out.println("I'm a person");
            }

            // 因为所有的class最终都继承自Object，而Object定义了几个重要的方法：
            // toString()：把instance输出为String；
            // equals()：判断两个instance是否逻辑相等；
            // hashCode()：计算一个instance的哈希值。
            // 在必要的情况下，我们可以OverRide覆写Object的这几个方法
            @Override
            public String toString() {
                return "Person{name='" + name + "'}";
            }
        }

        static class Student extends Person {
            private final String studentId;

            public Student(String name, String studentId) {
                super(name);
                this.studentId = studentId;
            }

            @Override
            public void introduce() {
                System.out.println("I'm a student");
            }

            @Override
            public String toString() {
                return "Student{" +
                        "name='" + super.toString() + '\'' +
                        ", studentId='" + studentId + '\'' +
                        '}';
            }
        }

        public static void main(String[] args) {
            System.out.println("覆写父类的方法（Override），覆写在子类中改变了父类方法的行为");
            Person person = new Student("Alice", "S12345");
            person.introduce(); // 输出：I'm a student
            System.out.println(person); // 调用重写的toString方法
        }
    }



    // ==================== 多态示例 ====================
    static class PolymorphismDemo {
        interface SoundMaker {
            void makeSound();
        }

        static class Animal implements SoundMaker {
            @Override
            public void makeSound() {
                System.out.println("Animal makes sound");
            }
        }

        static class Cat extends Animal {
            @Override
            public void makeSound() {
                System.out.println("Meow~");
            }
        }

        static class Dog extends Animal {
            @Override
            public void makeSound() {
                System.out.println("Woof!");
            }
        }

        public static void main(String[] args) {
            Animal[] animals = {new Cat(), new Dog(), new Animal()};
            Arrays.stream(animals).forEach(Animal::makeSound);
        }
    }

    // 多态具有一个非常强大的功能，就是允许添加更多类型的子类实现功能扩展，却不需要修改基于父类的代码
    public class PolymorphicFuncExample {

        class Income {
            protected double income;

            public Income(double income) {
                this.income = income;
            }

            public double getTax() {
                return income * 0.1; // 税率10%
            }
        }

        class Salary extends Income {
            public Salary(double income) {
                super(income);
            }

            @Override
            public double getTax() {
                if (income <= 5000) {
                    return 0;
                }
                return (income - 5000) * 0.2;
            }
        }

        // 国务院特殊津贴
        class StateCouncilSpecialAllowance extends Income {
            public StateCouncilSpecialAllowance(double income) {
                super(income);
            }

            @Override
            public double getTax() {
                return 0;
            }
        }
        public double totalTax(Income... incomes) {
            double total = 0;
            for (Income income: incomes) {
                total = total + income.getTax();
            }
            return total;
        }

        // 给一个有普通收入、工资收入和享受国务院特殊津贴的小伙伴算税:
        public void TaxDemo(){
            Income[] incomes = new Income[] {
                    new Income(3000),
                    new Salary(7500),
                    new StateCouncilSpecialAllowance(15000)
            };
            System.out.println(totalTax(incomes));
        }
    }


    // ==================== 转型示例 ====================
    static class CastingDemo {
        static class Animal {
            void eat() {
                System.out.println("Animal eating");
            }
        }

        static class Bird extends Animal {
            void fly() {
                System.out.println("Bird flying");
            }
        }

        public static void main(String[] args) {
            // 向上转型（upcasting）（安全）：把一个子类类型安全地变为父类类型的赋值
            // 向上转型实际上是把一个子类型安全地变为更加抽象的父类型
            // 继承树是Student > Person > Object
            Animal animal = new Bird();
            animal.eat();

            // 向下转型（需要类型检查）
            // 失败的时候，Java虚拟机会报ClassCastException
            // 能把父类变为子类，因为子类功能比父类多，多的功能无法凭空变出来
            if (animal instanceof Bird) {
                Bird bird = (Bird) animal;
                bird.fly();
            }

            // 不安全的转型示例
            try {
                Animal falseAnimal = new Animal();
                Bird falseBird = (Bird) falseAnimal; // 抛出ClassCastException
            } catch (ClassCastException e) {
                System.err.println("转型失败: " + e.getMessage());
            }
        }
    }


    public static void main(String[] args) {
        InheritanceDemo.main(args);
        OverloadDemo.main(args);
        OverrideDemo.main(args);
        PolymorphismDemo.main(args);
        CastingDemo.main(args);
    }


}
